package net.entelijan.cobean.table;

import java.awt.Dimension;
import java.util.ArrayList;
import java.util.List;

import net.entelijan.cobean.core.ColumnDesc;
import net.entelijan.cobean.core.ISingleSelectionListCobean;
import net.entelijan.cobean.core.impl.IPropertyChangeListenerAware;
import net.entelijan.cobean.table.DefaultSingleSelectionTableInitializer;

import org.fest.swing.fixture.FrameFixture;
import org.fest.swing.fixture.JTextComponentFixture;
import org.junit.Assert;
import org.junit.Test;

public class SortAndNotifyFestTestCase {

	/**
	 * Ensures that the cobean keeps its selected value when you apply a filter
	 * and that no extra events are fired
	 */
	@Test
	public void test01() {
		SortAndNotifyJFrame frame = new SortAndNotifyJFrame();
		FrameFixture frameFix = new FrameFixture(frame);
		try {
			frameFix.show(new Dimension(300, 300));

			final List<SortAndNotifyBean> beans = createTestBeans();

			DefaultSingleSelectionTableInitializer<SortAndNotifyBean> ini = new DefaultSingleSelectionTableInitializer<SortAndNotifyBean>();
			ini.setCoFilterInput(frame.getFilterTextField());
			ini.setCoTable(frame.getTable());
			ini.setColumnDescs(ColumnDesc.createFilterableSortableColumnDescs(
					"strVal", "intVal"));
			final ISingleSelectionListCobean<SortAndNotifyBean> cobean = ini
					.initialize();

			// Initialize the listeners and add them to the cobean
			final SortAndNotifyPropertyChangeListener valuePcl = new SortAndNotifyPropertyChangeListener(
					"value");
			final SortAndNotifyPropertyChangeListener selectedValuePcl = new SortAndNotifyPropertyChangeListener(
					"selectedValue");
			((IPropertyChangeListenerAware) cobean)
					.setPropertyChangeListener(valuePcl);
			((IPropertyChangeListenerAware) cobean)
					.setPropertyChangeListener(selectedValuePcl);

			{
				final SortAndNotifyBean selVal = cobean.getSelectedValue();
				Assert.assertNull(selVal);
				Assert.assertEquals("", valuePcl.getInfo());
				Assert.assertEquals("", selectedValuePcl.getInfo());
			}
			
			cobean.setValue(beans);
			cobean.setSelectedValue(beans.get(3));
			pause(1000);

			{
				final SortAndNotifyBean selVal = cobean.getSelectedValue();
				Assert.assertNotNull(selVal);
				Assert.assertEquals("D", selVal.getStrVal());
				Assert
						.assertEquals(
								"[propertyChange propName='value' oldVal='null' newVal='[SN(1,A), SN(2,B), SN(3,C), SN(4,D), SN(5,E)]']",
								valuePcl.getInfo());
				Assert
						.assertEquals(
								"[propertyChange propName='selectedValue' oldVal='null' newVal='SN(4,D)']",
								selectedValuePcl.getInfo());
			}
			final JTextComponentFixture textBox = frameFix
					.textBox("filterTextField");
			textBox.enterText("A");
			pause(1000);

			{
				final SortAndNotifyBean selVal = cobean.getSelectedValue();
				Assert.assertNotNull(selVal);
				Assert.assertEquals("D", selVal.getStrVal());
				Assert
						.assertEquals(
								"[propertyChange propName='value' oldVal='null' newVal='[SN(1,A), SN(2,B), SN(3,C), SN(4,D), SN(5,E)]']",
								valuePcl.getInfo());
				Assert
						.assertEquals(
								"[propertyChange propName='selectedValue' oldVal='null' newVal='SN(4,D)']",
								selectedValuePcl.getInfo());
			}
			textBox.deleteText();
			pause(1000);
//
//			{
//				final SortAndNotifyBean selVal = cobean.getSelectedValue();
//				Assert.assertNotNull(selVal);
//				Assert.assertEquals("D", selVal.getStrVal());
//				Assert
//						.assertEquals(
//								"[propertyChange propName='value' oldVal='null' newVal='[SN(1,A), SN(2,B), SN(3,C), SN(4,D), SN(5,E)]']",
//								valuePcl.getInfo());
//				Assert
//						.assertEquals(
//								"[propertyChange propName='selectedValue' oldVal='null' newVal='SN(4,D)']",
//								selectedValuePcl.getInfo());
//			}

		} finally {
			frameFix.cleanUp();
		}

	}

	private synchronized void pause(int ms) {
		try {
			this.wait(ms);
		} catch (InterruptedException e) {
			// Can be ignored
		}
	}

	private List<SortAndNotifyBean> createTestBeans() {
		ArrayList<SortAndNotifyBean> re = new ArrayList<SortAndNotifyBean>();
		re.add(new SortAndNotifyBean("A", 1));
		re.add(new SortAndNotifyBean("B", 2));
		re.add(new SortAndNotifyBean("C", 3));
		re.add(new SortAndNotifyBean("D", 4));
		re.add(new SortAndNotifyBean("E", 5));
		return re;
	}

}
